基础笔记2 您所在的位置:网站首页 三菱plc 整型转浮点 基础笔记2

基础笔记2

2024-07-09 12:12| 来源: 网络整理| 查看: 265

文章目录 说明数据在内存中的存储方式1.概念2.浮点数在内存中的存储方式 思路1:内存拷贝思路2:利用指针代码

说明

浮点数是不能进行位操作的,这就导致在进行数据拆分的时候非常麻烦。如果将其转换成整型,常用的办法是使用强制转换,虽然在原理上是利用不同的数据类型去读相同的二进制内容,但实际使用过程中往往会伴随着精度损失。

而且在一些控制场合,数据传输过程中需要将浮点数拆分成多个整型或者其他类型的数来进行传输,例如某控制器通过Modbus通信协议进行数据传输,但其寄存器只支持让你压short型的数据,你要在不损失精度的情况下,用2个short型数据去表示1个float型数据,我们应该怎么做呢?

数据在内存中的存储方式 1.概念

我们先来捋一遍概念,抛开编程语言来说,数据有8种基本类型:byte、short、int、long、float、double、bool、char,在进行拆分之前我们需要先了解一下各种数据类型的属性,以便能对数据进行正确的拆分。

byte

8位、有符号的以二进制补码表示的整数min : -128(-2^7)max: 127(2^7-1)default: 0

short

16位、有符号的以二进制补码表示的整数min : -32768(-2^15)max: 32767(2^15 - 1)default: 0

int

32位、有符号的以二进制补码表示的整数min : -2,147,483,648(-2^31)max: 2,147,483,647(2^31 - 1)default: 0

long

64位、有符号的以二进制补码表示的整数min : -9,223,372,036,854,775,808(-2^63)max: 9,223,372,036,854,775,807(2^63 -1)default: 0

float

单精度、32位、符合IEEE 754标准的浮点数float 在储存大型浮点数组的时候可节省内存空间浮点数不能用来表示精确的值,如货币default: 0.0f有效小数位 6位

double

双精度、64位、符合IEEE 754标准的浮点数浮点数的默认类型为double类型double类型同样不能表示精确的值,如货币default: 0.0d有效小数位 14位

char

char类型是一个单一的 16 位 Unicode 字符最小值是 \u0000(即为0)最大值是 \uffff(即为65,535)char 数据类型可以储存任何字符

bool

bool数据类型表示一位的信息只有两个取值:true 和 false这种类型只作为一种标志来记录 true/false 情况

对于其他概念,可以参考这篇博文1。

2.浮点数在内存中的存储方式

深入的研究请参考《IEEE754》标准。

一个浮点数在内存中由3部分来表达:符号位、底数m和指数e,值得注意的是它们都使用二进制来表示。

底数部分:使用2进制数来表示此浮点数的实际值。指数部分:占用8-bit的二进制数,可表示数值范围为0-255。

但是指数应可正可负,所以IEEE规定,此处算出的次方须减去127才是真正的指数。所以float的指数可从 -126到128.底数部分实际是占用24-bit的一个值,由于其最高位始终为 1 ,所以最高位省去不存储,在存储中只有23-bit。到目前为止, 底数部分 23位 加上指数部分 8位 使用了31位。那么前面说过,float是占用4个字节即32-bit,那么还有一位是干嘛用的呢? 还有一位,其实就是4字节中的最高位,用来指示浮点数的正负。

符号位:当最高位是1时,为负数,最高位是0时,为正数。

按上述表达方法,浮点数的存储格式如下:

Address+0Address+1Address+2Address+3内容SEEE EEEEEMMM MMMMMMMM MMMMMMMM MMMM

其中

S 表示浮点数正负,1为负数,0为正数E是指数加上127后的值的二进制数M是24-bit的底数(只存储23-bit)

值得注意的是,对于浮点数为0时,指数和底数都为0,上述公式不成立(2的0次方为1),对于这个特例,一般不需要人为去干扰,编译器会自动识别

具体转换例子可参考这篇文章2。

有了前面的基础,我们接下来去试着拆分一下:

思路1:内存拷贝

因为所有数据在计算机中都是以二进制的形式储存的,因此可以考虑使用C标准库提供的memcpy将float拷贝到缓冲区中再编辑。 (实践证明不太可行,虽然原理上行得通)

//验证思路是否正确 #include #include using namespace std; int main() { float data1 = 123.456; unsigned int uiData; float data2; memcpy(&uiData, &data1, 32); memcpy(&data2, &uiData, 32); cout short spArr[2]; //小端分解 // *spArr = (short) ((iVal >> 16) & 0xFFFF); // *(spArr + 1)= (short)(iVal & 0xFFFF); //大端分解 spArr[0] = (short)(iVal & 0xFFFF); spArr[1] = (short)((iVal >> 16) & 0xFFFF); return spArr; } short* InsertFloatVarToModbusShortArr(float fVal) { //待优化 short spArr[2]; short* spArrTemp = (short*)&fVal; spArr[0] = spArrTemp[0]; spArr[1] = spArrTemp[1]; return spArr; } float InsertModbusShortArrToFloatVar( short* spArr) { short dataTemp[2]; dataTemp[0] = *spArr; dataTemp[1] = *(spArr + 1); return *((float*)dataTemp); } int main() { int data1 = 8; float data = 17.625; short a[2] = {0,16781}; short *b; float c; short *data2; data2 = InsertIntVarToModbusShortArr(data1); cout


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有